package com.atguigu.mybatis.demo;

import com.atguigu.mybatis.bean.Employee;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Smexy on 2022/11/29
 *
 *    任何对数据库进行读写的操作都有一个套路:
 *          ①创建连接
 *          ②准备读写命令
 *          ③执行命令
 *          ④是读，获取结果
 *          ⑤关闭连接
 *    ---------------------------
 *      以redis为例:
 *          ①Jedis a = new Jedis()
 *          ②③④  String res = a.ping()
 *          ⑤ a.close()
 *
 *    --------------------------------
 *      JDBC:  连接是Connection
 *      Mybatis:  SqlSession
 *
 *
 *    -----------------------------
 *      如何创建一个对象：
 *              直接:  调用构造方法。
 *                        A a =  new A()
 *
 *              A的构造方法是private或是protected，无法调用！
 *              参考提供的设计模式:
 *                     建造者模式: A a = new ABuilder().build();
 *
 *                     工厂模式:  A a = new AFactory().getInstance();
 *
 *    -------------------------------
 *    Caused by: org.apache.ibatis.executor.ExecutorException:
 *    // 查询已经运行
 *      A query was run
 *      and no Result Maps were found for the Mapped Statement 'hao.sql1'.
 *      //hao.sql1 既没有指定  Result Type  又没有指定 Result Map
 *      It's likely that neither a Result Type nor a Result Map was specified.
 *
 *    ---------------------
 *      属性的封装规则:
 *              Object o = sqlSession.selectOne("hao.sql1");
 *              本质：发送sql
 *                   select * from employee where id = 1
 *              被mysql服务器执行:
 *                  返回结果:
 *
 *                  id  last_name  gender  email
             * ------  ---------  ------  -------------
             *      1  Tom        male    Tom@163.com
 *
 *
 *          利用反射，创建 com.atguigu.mybatis.bean.Employee对象。
 *               Employee e  = new Employee();
 *
 *           查询的列的名字叫什么，例如xx，调用 e.setXx(列值)。
 *                        e.setId(1);
 *                        e.setLast_name('Tom');
 *                        e.setGender('male')
 *                        e.setEmail('Tom@163.com')
 *
 *                 Employee(id=1, lastName=null, gender=male, email=Tom@163.com)
 *
 *    ------------------------------
 *      解决办法:
 *              方法一:提供一个setLast_name()
 *              方法二：
 *                      现成的e.setLastName()，只需要让列名为 lastName
 *              方法三：
 *                      sql写*，希望mybatis自动把不符合java命名风格的 下划线命名转为 驼峰式
 *                          last_name ----->mybatis自动转换 -----> lastName
 *
 *
 *   ------------------------------
 *      <T> T selectOne()
 *              传入泛型，需要  xxx.<T>selectOne
 *   -------------------
 *      hello world的问题:
 *              ① 调用是Mybatis提供好的方法，不传入泛型，默认返回Object
 *                      要使用的话，需要强转。
 *                      或明确指定泛型
 *
 *              ②调用的是Mybatis提供好的方法，方法的参数列表是固定的，只能传入Object，
 *                      对传入的类型是没有约束。
 *                      编译时，检查通过。执行时，可能由于类型不匹配报错
 *
 *
 *            如何解决?
 *                  自主创新(接口式编程)！
 *                  我只调用自己写的方法！
 *                         Employee  getEmployeeById(Integer id);
 *
 *
 *
 */
public class HelloWorld
{
    public static void main(String[] args) throws IOException {

        /*


                凡框架必有配置文件
                    mybatis_config.xml： mybatis的全局配置文件。名字随便！格式必须符合要求！
         */
        // ①创建一个 SqlSessionFacttory
        String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // ②获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // ③准备读写命令  以 查询一号员工为例
        // selectOne(String statement, Object parameter)
        Object o = sqlSession.selectOne("hao.sql1",sqlSession);


        //Employee one = sqlSession.<Employee>selectOne("hao.sql1", 2);

        Employee employee = (Employee) o;

        System.out.println(employee);

        // ④关闭连接
        sqlSession.close();

    }
}
